//
//  TSCMySpinner2.m
//  Tsc_IOS
//
//  Created by Rio on 15-5-27.
//  Copyright (c) 2015年 idream. All rights reserved.
//
// TODO 计算绝对高度时，可能因为self并不在vc.view中（可能自己未被添加到vc.view，或者自己所在的父view、爷爷view没有被添加到vc.view），而导致计算错误，显示结果不正确！
// TODO 给table添加阴影，否则可能导致与同色的背景重合时，看不清table边界
// -- TODO 添加手势图层时，below的对象不一定是self，也可能是self.superview，甚至更高层级


#define ICON_WH 10 // 右侧倒三角的宽高
#define ICON_PADDING 5 // 右侧倒三角距离右边沿的padding
#define TABLE_INIT_H 200 // UITableView的初始高度
#define TABLE_ROW_HEIGHT 30 // UITableView中默认的行高。注：XCODE 6.2中，UITableView不再提供默认的rowHeight

typedef enum {TABLE_UP, TABLE_DOWN} TABLE_UP_OR_DOWN;

#import "TSCMySpinner.h"
#import "TSCMyUtil.h"
#import "TSCConstants.h"
#import "TSCMyUIUtil.h"

@implementation TSCMySpinner {
    UIButton * _btn;
    UIImageView * _icon;
    UITableView * _table;
    UIImageView * _gestureLayer; // 隐藏手势图层，用于关闭table
}

#pragma mark 初始化方法

- (id)initWithFrame:(CGRect)frame
{
    self = [super initWithFrame:frame];
    if (self) {
        // Initialization code
        
        // 初始化TableView
        [self initUI];
    }
    return self;
}

- (id)init {
    self = [super initWithFrame:CGRectMake(0, 0, 0, 0)];
    if (self) {
        // 初始化TableView
        [self initUI];
    }
    return self;
}

/*
 // Only override drawRect: if you perform custom drawing.
 // An empty implementation adversely affects performance during animation.
 - (void)drawRect:(CGRect)rect
 {
 // Drawing code
 }
 */

/* private */ - (void) initUI {
    
    // ===== 初始化数据源
    
    _dataArray = [NSMutableArray array];
    
    // ===== 设置btn_panel
    // 设置btn
    _btn = [UIButton buttonWithType:UIButtonTypeSystem];
    [TSCMyUIUtil setUIRoundBorder:_btn radius:5.0 borderColor:COLOR_MT borderWidth:1.0]; // 设置btn圆角边框
    _btn.frame = CGRectMake(0, 0, 0, 0); // 注：初始化时不设置frame，等到设置spinner.frame/center/bounds时，再同时设置
    [_btn setTitleColor:[UIColor blackColor] forState:UIControlStateNormal]; // 设置字体颜色
    _btn.contentHorizontalAlignment = UIControlContentHorizontalAlignmentFill; // 文字左对齐
    _btn.contentEdgeInsets = UIEdgeInsetsMake(0, ICON_PADDING, 0, 0); // 文字左侧空出padding位置
    [_btn addTarget:self action:@selector(btnTouchDown) forControlEvents:UIControlEventTouchDown]; // 注册事件——btn区域按下后，显示table
    
    // 设置右侧图标
    _icon = [[UIImageView alloc]initWithImage:[UIImage imageNamed:@"ic_down_triangle_96x96.png"]];
    _icon.frame = CGRectMake(0, 0, ICON_WH, ICON_WH); // 注：初始化时不设置位置，等到设置spinner.frame/center/bounds时，再同时设置
    
    // 添加btn、icon
    [self addSubview:_btn];
    [self addSubview:_icon];
    
    // ===== 设置table
    _table = [[UITableView alloc] initWithFrame:CGRectMake(0, 0, 0, TABLE_INIT_H) style:UITableViewStylePlain]; // 注：初始化时不设置frame，等到设置spinner.frame/center/bounds时，再同时设置
    _table.rowHeight = TABLE_ROW_HEIGHT; // 默认行高
    _table.separatorStyle = UITableViewCellSeparatorStyleSingleLine;
    _table.scrollEnabled = YES;
    _table.backgroundColor = COLOR_TRANSPARENT;
    
    // TODO 设置table阴影
//    [TSCMyUIUtil setUIRoundBorder:_table radius:1.0 borderColor:[UIColor blackColor] borderWidth:1.0];
    //路径阴影
//    [[_table layer] setShadowColor:[UIColor grayColor].CGColor]; // 阴影的颜色
//    [[_table layer] setShadowOffset:CGSizeMake(5, 5)]; // 阴影的范围
//    [[_table layer] setShadowRadius:2];                // 阴影扩散的范围控制
//    [[_table layer] setShadowOpacity:1];               // 阴影透明度

   
    
    
    
    // 设置table数据源及代理
    _table.dataSource = self;
    _table.delegate = self;
    
    // ===== 设置手势图层
    
    // 以全屏大小创建隐藏图层
    _gestureLayer = [[UIImageView alloc]init];
    _gestureLayer.backgroundColor = COLOR_TRANSPARENT;
    _gestureLayer.frame = CGRectMake(0, 0, UI_SCREEN_WIDTH, UI_SCREEN_HEIGHT);
    
    // 注册事件——点击后，关闭table。相当于只要手势没有点击在选择框内，就关闭table
    _gestureLayer.userInteractionEnabled = YES;
    [_gestureLayer addGestureRecognizer:[[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(gestureLayerClicked)]];
    
}

#pragma mark 设置大小及位置

- (void) setFrame:(CGRect)frame {
    [super setFrame:frame];
    
    // 重新布局UI
    [self relayoutUI];
}

- (void) setCenter:(CGPoint)center {
    [super setCenter:center];
    
    // 重新布局UI
    [self relayoutUI];
}

- (void) setBounds:(CGRect)bounds {
    [super setBounds:bounds];
    
    // 重新布局UI
    [self relayoutUI];
}

// 当使用了setFrame()、setCenter()、setBounds()、或显示table之后，需要重新绘制UI
/* private */ - (void) relayoutUI {
    CGRect rf = self.frame; // spinner相对于父元素的frame
    CGRect af = [self.superview convertRect:rf toView:[TSCMyUtil getCurrentViewController].view]; // spinner相对于窗口的绝对frame
    
    // 绘制btn（相对于spinner.frame）
    _btn.frame = CGRectMake(0, 0, rf.size.width, rf.size.height);
    
    // 绘制icon（相对于spinner.frame）
    _icon.frame = CGRectMake(rf.size.width - ICON_PADDING - ICON_WH, rf.size.height / 2 - ICON_WH / 2, ICON_WH, ICON_WH);
    
    // 绘制table（将spinner.frame转换为绝对frame）
    if ([self calculateTableDirection] == TABLE_DOWN) {
        _table.frame = CGRectMake(af.origin.x, af.origin.y + af.size.height, af.size.width, _table.frame.size.height);
    } else {
        _table.frame = CGRectMake(af.origin.x, af.origin.y - _table.frame.size.height, af.size.width, _table.frame.size.height);
    }
}

// 设置完数据源后，需要重新设置table高度
/* private */ - (void)resetTabelH {
    
    // spinner相对于窗口的绝对frame
    CGRect af = [self.superview convertRect:self.frame toView:[TSCMyUtil getCurrentViewController].view];
    
    // 所有行的总高度
    CGFloat rowsH = _table.rowHeight * [_dataArray count];
    
    // spinner上/下边沿距离屏幕顶部/底部的剩余高度
    CGFloat remainScreenH = 0;
    if ([self calculateTableDirection] == TABLE_DOWN) {
        remainScreenH = UI_SCREEN_HEIGHT - (af.origin.y + af.size.height);
    } else {
        remainScreenH = af.origin.y;
    }
    
    // 取3者最小值
    CGFloat tableH = TABLE_INIT_H;
    if (rowsH < tableH) {
        tableH = rowsH;
    }
    if (remainScreenH < tableH) {
        tableH = remainScreenH;
    }
    
    _table.bounds = CGRectMake(0, 0, _table.bounds.size.width, tableH);
    
    // ===== 设置完table高度后，还需要同步更新table的Y值
    
    // 重新获得绝对frame
    af = [self.superview convertRect:self.frame toView:[TSCMyUtil getCurrentViewController].view];
    
    CGFloat tableY = 0;
    if ([self calculateTableDirection] == TABLE_DOWN) {
        tableY = af.origin.y + self.frame.size.height;
    } else {
        tableY = af.origin.y - _table.frame.size.height;
    }
    
    // 重新设置table的位置
    _table.frame = CGRectMake(_table.frame.origin.x, tableY, _table.frame.size.width, _table.frame.size.height);
}

#pragma mark Getters & Setters

- (void) setFont:(UIFont *)font {
    _font = font;
    _btn.titleLabel.font = font;
   // 还需要设置TableCell中的font。注：在cellForRowAtIndexPath中设置
}

- (UIFont *) _font {
    return _font;
}

#pragma mark 公共方法

/**
 * 数据准备。完全运行在异步线程中，不涉及UI操作。因为数据准备可能是耗时的。
 *
 * @date 2015-05-25
 * @author Rio
 */
- (void) prepareData_P1:(void (^)())preparingHandler completionHandler:(void (^)())completionHandler {
    // 参数检查
    NSAssert(preparingHandler != nil, @"[E]%s: MySpinner数据准备block为nil！", __FUNCTION__);
    
    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
        // 数据源准备
        // 注：执行之后，应该保证数据源不为nil，且不能没有任何数据项
        preparingHandler();
        
        // 检查数据源是否被正确设置
        //        NSAssert(_dataArray != nil, @"[E]%s: MySpinner设置数据源后，数据源依然为nil！", __FUNCTION__);
        if ([_dataArray count] ==0) {
            NSLog(@"[W]%s: MySpinner设置数据源后，数据源依然没有任何数据！可能影响后续UI显示！", __FUNCTION__);
        }
        
        // 回到主线程
        dispatch_async(dispatch_get_main_queue(), ^{
            // 执行回调
            if (completionHandler) {
                completionHandler();
            }
        });
    });
}

- (void) cleanData {
    _dataArray = [NSMutableArray array];
}

- (void) applyData {
    [_btn setTitle:@"" forState:UIControlStateNormal]; // 将btn上可能存在的历史显示清除
    [_table reloadData];
    [self resetTabelH]; // 重新设置table高度
    
    // 默认选择第一项
    if ([_dataArray count] >= 1) {
        [self setSelectedItem:0];
    }
}

- (NSIndexPath *) getSelectedIndexPath {
    return [_table indexPathForSelectedRow];
}

- (id) getSelectedObject {
    NSIndexPath * ip = [self getSelectedIndexPath];
    
    // 注：如果ip为nil不加以判断，将把ip.row作为0，即返回第一个元素。显然这样做时不对的
    if (ip) {
        return [_dataArray objectAtIndex: ip.row];
    } else {
        return nil;
    }
}

- (void) setSelectedItem:(NSInteger)selectedItemIndex {
    // 获得所选index位置上的IndexPath
    NSIndexPath * selectedItemIndexPath = [_table indexPathForRowAtPoint:CGPointMake(0, _table.rowHeight * selectedItemIndex)];
    
    // 获得选择的cell字符串内容
    UITableViewCell * cell = [_table cellForRowAtIndexPath:selectedItemIndexPath];
    NSString * text = cell.textLabel.text;
    
    // 显示到btn
    [_btn setTitle:text forState:UIControlStateNormal];
    
    // 使table也选中此项
    // 住：除非用户在界面手工选择table中的某一项，否则table并不知道自己的哪一项被选择了
    [_table selectRowAtIndexPath:selectedItemIndexPath animated:NO scrollPosition:UITableViewScrollPositionBottom];
    
    // 关闭table
    [self dismissTable];
    
    // item被选中后的回调
    if (_itemSelectedListener) {
        _itemSelectedListener(self, cell, selectedItemIndexPath);
    }
}

#pragma mark 私有方法

// 根据btn在屏幕的位置，计算table应该显示在上方，还是下方
/* private */ - (TABLE_UP_OR_DOWN) calculateTableDirection {
    // 获得spinner的绝对center
    // TODO 注：可能得到不正确的结果，因为可能此时spinner并没有被添加到vc中，所以绝对位置无法计算！
    //    CGPoint absCenter = [TSCMyUtil getAbsoluteCenter:self];
    CGPoint absCenter = [self.superview convertPoint:self.center toView:[TSCMyUtil getCurrentViewController].view];
    
    if (absCenter.y > (UI_SCREEN_HEIGHT / 2)) {
        return TABLE_UP;
    } else {
        return TABLE_DOWN;
    }
}

/* private */ - (void) showTable {
    // 显示table
    UIViewController * currentVC = [TSCMyUtil getCurrentViewController];
    [currentVC.view addSubview:_table];
    _table.tag = YES; // 打标记，表示已经被显示
    
    // 重新布局UI
    [self relayoutUI];
    
    // 显示手势图层
    [currentVC.view insertSubview:_gestureLayer belowSubview:_table]; // 注：需要将手势图层添加到table后面
}

/* private */ - (void) dismissTable {
    // 移除table
    [_table removeFromSuperview];
    _table.tag = NO; // 打标记，表示已经被关闭
    
    // 移除手势图层
    [_gestureLayer removeFromSuperview];
}

/* private */ - (BOOL) isTableShowing {
    if (_table.tag) {
        return YES;
    } else {
        return NO;
    }
}


/* private */ - (void) gestureLayerClicked {
    // 关闭table
    [self dismissTable];
}


#pragma mark UIButton及其代理的声明周期方法

// 点击时，如果未显示，则显示；如果已显示，则关闭
- (void) btnTouchDown {
    if ([self isTableShowing] == NO) {
        // 显示tb和手势图层
        [self showTable];
    } else {
        // 隐藏tb和手势图层
        [self dismissTable];
    }
}
// 注：点击屏幕空白区域，收回键盘，应该在vc中重写touchesEnded()方法

#pragma mark UITableView及其代理的生命周期方法

// 获得总行数
- (NSInteger) tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
    return [_dataArray count];
}

// 每一行内容是什么
- (UITableViewCell *) tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
    
    // 如果指定了如何创建cell，则使用自定义cell创建方法
    if (_cellCreator) {
        return _cellCreator(tableView, indexPath);
    } else {
        static NSString *cellReuseId = @"textCell";
        UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:cellReuseId];
        if (cell == nil) {
            cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:cellReuseId];
            cell.backgroundColor = COLOR_MT_SPINNER_CELL_BG;
        }
        NSUInteger row = [indexPath row];
        NSString * text = [_dataArray objectAtIndex:row];
        if ([text isKindOfClass:[NSString class]] == NO) {
            NSLog(@"[W]%s: MySpinner数据源中，存在不是NSString类型的数据！显示时将抛出异常！数据源中的对象：%@", __FUNCTION__, text);
            
            // 设置为错误提示
            text = @"数据源类型不是NSString！";
        }
        
        cell.textLabel.text = text;
        
        // 使用自定义的字体
        if (_font) {
            cell.textLabel.font = _font;
        }
        //    cell.imageView.image = [UIImage imageNamed:@"ic_app_logo_96x96.png"];
        //    cell.detailTextLabel.text = @"详细信息";
        
        // 应用简版cell构造器
        if (_cellModifier) {
            _cellModifier(tableView, cell, indexPath);
        }
        
        return cell;
    }
}

// 注册事件——选择某行后
- (void) tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
    [self setSelectedItem:indexPath.row];
}


@end
